﻿package edu.hit.irlab.coref.corpus.converter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.StringReader;
import java.util.Scanner;
import java.util.HashMap;
import java.util.ArrayList;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

public class ConverterXunFeiImpl extends Converter {
	private int currentEntityId = -1;
	private int currentSeek = 0;
	private Document dom = null; //	最终要返回的DOM树
	private Element root = null;
	
	private class Metion {
		public String extentStart;
		public String extentEnd;
		public String extentContent;
		public String headContent;
		public String headStart;
		public String headEnd;
		
		public Metion() {}
	}
	
//	!!!!!!!!暂用来生成 文xml文 件的
	private int nnnnnn = 0;

	@Override
	public Document transform(File remoteXML) {
		this.currentEntityId = -1;
		this.currentSeek = 0;
		this.dom = null;
		this.root = null;
		
		try {
			Document dom = DocumentHelper.createDocument();
			root = dom.addElement(DOCUMENT);
			root.attributeValue(DOCID, remoteXML.getName());
			
			InputStreamReader reader = new InputStreamReader(new FileInputStream(remoteXML), "utf-8");
			Scanner scanner = new Scanner(reader);
			HashMap<String, ArrayList<Metion>> metionMap = new HashMap<String, ArrayList<Metion>>();
			HashMap<String, Element> entities = null; //	暂时保持entity的词典
			while (scanner.hasNextLine()) {
				String line = scanner.nextLine();
//				line = line.replaceAll(" ", "");
				
				if (line.startsWith("a") && line.endsWith(";")) {
					//	共指信息
					compile(metionMap, line, entities); //	解释共指信息语句
					
					this.currentSeek += 1; //	换行符
				} else {
					//	原句行,找出所以标注信息,把句中的标注实体存入字典中，方便在后面读入共解信息后调用
					entities = checkLine(metionMap, line);
					
					this.currentSeek += 1;
				}
				
			}
			
//			Transformer t = TransformerFactory.newInstance().newTransformer();
//			t.setOutputProperty(OutputKeys.INDENT, "yes");
//			t.transform(dom, new StreamResult(new FileOutputStream("a" + nnnnnn++ + ".xml")));
		} catch (Exception ex) {
			ex.printStackTrace();
			dom = null;
		}
		
		return dom;
	}
	
	@Override
	public String getDocumentString(Document dom) {
		
		return null;
	}	
	
	private void addMention(HashMap<String, ArrayList<Metion>> metionMap, String key, Metion metion) {
		if (metionMap.get(key) == null) {
			ArrayList<Metion> array = new ArrayList<Metion>();
			array.add(metion);
			metionMap.put(key, array);
		} else {
			metionMap.get(key).add(metion);
		}
	}
	
	private HashMap<String, Element> checkLine(HashMap<String, ArrayList<Metion>> metionMap, String line) throws Exception {
		metionMap.clear();
		int i = 0;
		while (true) {
			int t = line.substring(i).indexOf("##");
			if (t == -1) {
				break;
			} else {
				this.currentSeek -= 2;
			}
			
			i = i + t + 2; //	"##"后的字符的脚标
			
			t = line.substring(i).indexOf("##a");
			if (t == -1) {
				throw new Exception("lack of string \"##a\"");
			} 
			
			String[] list = line.substring(0, i + t).split(" ");
			int offset = list.length - 1;
			
			Metion newMetion = new Metion();
			newMetion.extentContent = line.substring(i, i + t).replaceAll(" ", "");
			newMetion.extentEnd = String.valueOf(i + t + this.currentSeek - 1 - offset);
			newMetion.extentStart = String.valueOf(i + t + this.currentSeek - offset - newMetion.extentContent.length());
			newMetion.headContent = list[list.length - 1].replaceAll("#", "");
			if ("()".equals(newMetion.headContent)) {
				newMetion.headContent = list[list.length - 2];
			}
			newMetion.headEnd = newMetion.extentEnd;
			newMetion.headStart = String.valueOf(i + t + this.currentSeek -  offset - newMetion.headContent.length());
			
			this.currentSeek -= 3;
			
			i = i + t + 3; //	从a后面的数字开始
			for (t = 0; (i + t) < line.length() && '0' <= line.charAt(i + t) && line.charAt(i + t) <= '9'; t++); //	循环指向不是数字的第一个字符
			this.currentSeek -= t;
			
			
			String key = line.substring(i, i + t); //	如果a1, 那么key=‘1’
			addMention(metionMap, key, newMetion);
			
			if (i + t == line.length())
				break;
			i = i + t;
		}
		
		//	currentSeek增加
		this.currentSeek += line.length();
		
		//		再把HashMap里的所有实体写入DOM树
		int ii = 0; //	entity中孩子metion的ID, 把它外提是因为它要在整个文件中累加
		HashMap<String, Element> entities = new HashMap<String, Element>(); //	把新生成的entity暂存在词典中，方便后面的使用查找
		for (int j = 1, jj = 1; j <= metionMap.size(); j++, jj++) { //		j保证实体数量正确，jj用来指定实体的ID
			String key = String.valueOf(jj);
			Element entity = DocumentHelper.createElement(ENTITY);
			entity.attributeValue(ID, String.valueOf(Integer.parseInt(key) + this.currentEntityId));
			
			boolean isNewMetion = true;
			
			while (metionMap.get(key) == null) {
				jj++;
				key = String.valueOf(jj);
			}
			for (Metion metion : metionMap.get(key)) { //	metionMap.get(String) 返回ArrayList<Metion>
				Element metionElement = DocumentHelper.createElement(MENTION);
				metionElement.attributeValue(ID, String.valueOf(ii));
				if (isNewMetion) {
					isNewMetion = false;
				} else {
					metionElement.attributeValue("REF", String.valueOf(ii - 1));
				}
				
				//set the extent
				Element extent = DocumentHelper.createElement(EXTENT);
				extent.attributeValue(START, metion.extentStart);
				extent.attributeValue(END, metion.extentEnd);
				extent.setText(metion.extentContent);
				metionElement.add(extent);
				
				//set the head
				Element head = DocumentHelper.createElement(HEAD);
				head.attributeValue(START, metion.headStart);
				head.attributeValue(END, metion.headEnd);
				head.setText(metion.headContent);
				metionElement.add(head);
				
				entity.add(metionElement);
				
				ii++;
			}
			
			entities.put(key, entity);
			root.add(entity);
		}
		
		this.currentEntityId += metionMap.size(); //	下一个entity ID减1
		
		return entities;
	}
	
	private void compile(HashMap<String, ArrayList<Metion>> metionMap, String line, HashMap<String, Element> entities) {
		//	先暂时实现现有语料的所用到的语法，这个语法是迅飞所制定语法的一个子集
		
		//	对过解释共指信息，设置各entity的属性
		Scanner scanner = new Scanner(new StringReader(line));
		String key = scanner.findInLine("\\d+");
		String operor = scanner.findInLine("<|=");
		
		if ("<".equals(operor)) {
			String key2 = scanner.findInLine("\\d+");
			entities.get(key).attributeValue(PARENTID, entities.get(key2).attributeValue(ID));
		} else if ("=".equals(operor)) {
			String key2 = null;
			while ((key2 = scanner.findInLine("\\d+")) != null) {
				entities.get(key2).attributeValue(PARENTID, entities.get(key).attributeValue(ID));
			}
		} else {
			System.out.println("!!!!!error on reading operor");
		}
	}

	@Override
	public String getDocumentString(Document doc, String sourceDocPath) {
		// TODO Auto-generated method stub
		return null;
	}


}

